package net.bingosoft.common.struts.tags;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;

import net.bingosoft.common.config.Config;
import net.bingosoft.common.struts.BaseLazyDynaForm;

import org.apache.commons.lang.StringUtils;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.FormBeanConfig;
import org.apache.struts.taglib.TagUtils;
import org.apache.struts.taglib.html.Constants;
import org.apache.struts.taglib.html.FormTag;
import org.apache.struts.util.RequestUtils;

/**
 * 2007-11-23 下午01:54:30
 * Author:yangdongyu(yangdy@bingosoft.net)
 * ReadMe:支持自动验证的form标签
 * ChangeLog:
 */
public class ValidateFormTag extends FormTag {
	
	private static final long serialVersionUID = 1L;
	private boolean isXhtml = false;
	private static final String errorDiv = "<div id=\"_error_summary\" class=\"Validator_Summary\" style=\"display:none\"></div>";
	/**
	 * 验证脚本的路径
	 */
	private static final String VALIDATOR_SCRIPT_PATH = Config.getString("VALIDATOR_SCRIPT_PATH", "/script/validator/Validator.js");
	/**
	 * 默认不开启验证
	 */
	private boolean validate = Config.getBoolean("FORM_VAILIDATE", false);
	
	private String name;
	/**
	 * 验证的提示类型(默认采用alert对话框)
	 */
	private int alertType = 6;
	
	
    public int getAlertType() {
		return alertType;
	}
    
	public void setAlertType(int alertType) {
		this.alertType = alertType;
	}
	public boolean getValidate() {
		return validate;
	}
	
	public void setValidate(boolean validate) {
		this.validate = validate;
		if(this.validate && this.onsubmit == null){
			this.onsubmit = "return Validator.Validate(this);";
		}
	}
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
    /**
     * Render the beginning of this form.
     *
     * @exception JspException if a JSP exception has occurred
     */
    public int doStartTag() throws JspException {
    	if(this.name != null){
    		this.beanName = this.name;
    	}else{
    		//Look up the form bean name, scope, and type if necessary
            this.lookup();
    	}
        

        // Create an appropriate "form" element based on our parameters
        StringBuffer results = new StringBuffer();
        
        results.append(this.renderFormStartElement());

        results.append(this.renderToken());

        TagUtils.getInstance().write(pageContext, results.toString());

        // Store this tag itself as a page attribute
        pageContext.setAttribute(Constants.FORM_KEY, this, PageContext.REQUEST_SCOPE);

        this.initFormBean();

        return (EVAL_BODY_INCLUDE);

    }

    /**
     * Render the end of this form.
     *
     * @exception JspException if a JSP exception has occurred
     */
    public int doEndTag() throws JspException {

        // Remove the page scope attributes we created
        pageContext.removeAttribute(Constants.BEAN_KEY, PageContext.REQUEST_SCOPE);
        pageContext.removeAttribute(Constants.FORM_KEY, PageContext.REQUEST_SCOPE);

        // Render a tag representing the end of our current form
        StringBuffer results = new StringBuffer("</form>");

        // Render JavaScript to set the input focus if required
        if (this.focus != null) {
            results.append(this.renderFocusJavascript());
        }
        if(this.validate){
        	results.append(renderValidateJS());
        }
        // Print this value to our output writer
        JspWriter writer = pageContext.getOut();
        try {
            writer.print(results.toString());
        } catch (IOException e) {
            throw new JspException(messages.getMessage("common.io", e.toString()));
        }

        // Continue processing this page
        return (EVAL_PAGE);

    }
    /**
     * Generates the opening <code>&lt;form&gt;</code> element with appropriate
     * attributes.
     * @since Struts 1.1
     */
    protected String renderFormStartElement() {
        StringBuffer results = new StringBuffer();
        if((alertType & 8) == 8){
        	results.append(errorDiv);
        }
        results.append("\n<form");
        // render attributes
        if (!isXhtml) {
            renderName(results);
        }
        renderAttribute(results, "method", getMethod() == null ? "post" : getMethod());
        renderAction(results);
        renderAttribute(results, "accept-charset", getAcceptCharset());
        renderAttribute(results, "class", getStyleClass());
        renderAttribute(results, "enctype", getEnctype());
        renderAttribute(results, "onreset", getOnreset());
        renderAttribute(results, "onsubmit", getOnsubmit());
        renderAttribute(results, "style", getStyle());
        renderAttribute(results, "id", getStyleId() == null ? beanName : getStyleId());
        renderAttribute(results, "target", getTarget());

        // Hook for additional attributes
        renderOtherAttributes(results);

        results.append(">");
        return results.toString();
    }
    /**
     * Locate or create the bean associated with our form.
     * @throws JspException
     * @since Struts 1.1
     */
    protected void initFormBean() throws JspException {
        String scope = "request";
        if ("session".equalsIgnoreCase(beanScope)) {
            scope = "session";
        }        
        Object bean = TagUtils.getInstance().lookup(pageContext, beanName, scope);
        if (bean == null) {
            // New and improved - use the values from the action mapping
        	bean = (mapping != null && moduleConfig!=null) ?
                    RequestUtils.createActionForm(
                        (HttpServletRequest) pageContext.getRequest(),
                        mapping,
                        moduleConfig,
                        servlet) : new BaseLazyDynaForm();
            if (bean instanceof ActionForm) {
                ((ActionForm) bean).reset(mapping, (HttpServletRequest) pageContext.getRequest());
            }
            if (bean == null) {
                throw new JspException(messages.getMessage("formTag.create", beanType));
            }
            pageContext.setAttribute(beanName, bean, TagUtils.getInstance().getScope(scope));
        }
        pageContext.setAttribute(Constants.BEAN_KEY, bean, PageContext.REQUEST_SCOPE);
    }
    /**
     * 输出验证js
     * @return
     */
    public String renderValidateJS(){
    	
    	 StringBuffer results = new StringBuffer();

         results.append(lineEnd);
         results.append("<script type='text/javascript' src='").append(((HttpServletRequest)pageContext.getRequest()).getContextPath()).append(VALIDATOR_SCRIPT_PATH).append("'></script>");
         results.append(lineEnd);
         results.append("<script type='text/javascript'>");
         results.append(lineEnd);
         if (!isXhtml) {
             results.append("  <!--");
             results.append(lineEnd);
         } 
         results.append("Validator.Setup({Name : '").append(StringUtils.isNotEmpty(this.styleId) ? this.styleId : this.beanName).append("',AlertType:").append(this.alertType).append("});");
         results.append(lineEnd);
         if (!isXhtml) {
             results.append("  // -->");
             results.append(lineEnd);
         }

         results.append("</script>");
         results.append(lineEnd);
         return results.toString();
    }
    /**
     * Look up values for the <code>name</code>, <code>scope</code>, and
     * <code>type</code> properties if necessary.
     *
     * @exception JspException if a required value cannot be looked up
     */
    protected void lookup() throws JspException {

        // Look up the module configuration information we need
        moduleConfig = TagUtils.getInstance().getModuleConfig(pageContext);

        if (moduleConfig == null) {
            JspException e = new JspException(messages.getMessage("formTag.collections"));
            pageContext.setAttribute(Globals.EXCEPTION_KEY, e, PageContext.REQUEST_SCOPE);
            throw e;
        }
        servlet =
            (ActionServlet) pageContext.getServletContext().getAttribute(
                Globals.ACTION_SERVLET_KEY);

        // Look up the action mapping we will be submitting to
        String mappingName = TagUtils.getInstance().getActionMappingName(action);
        mapping = (ActionMapping) moduleConfig.findActionConfig(mappingName);
        if (mapping == null) {
            JspException e = new JspException(messages.getMessage("formTag.mapping", mappingName));
            pageContext.setAttribute(Globals.EXCEPTION_KEY, e, PageContext.REQUEST_SCOPE);
            throw e;
        }

        // Look up the form bean definition
        FormBeanConfig formBeanConfig = moduleConfig.findFormBeanConfig(mapping.getName());
        Object form = TagUtils.getInstance().lookup(pageContext, mapping.getAttribute(), mapping.getScope());
        String type = null;
        if(form != null && form instanceof BaseLazyDynaForm){
        	type = form.getClass().getName();
        }
        if (formBeanConfig == null && form == null) {
            JspException e =
                new JspException(messages.getMessage("formTag.formBean", mapping.getName(), action));
            pageContext.setAttribute(Globals.EXCEPTION_KEY, e, PageContext.REQUEST_SCOPE);
            throw e;
        }

        // Calculate the required values
        beanName = mapping.getAttribute();
        beanScope = mapping.getScope();
        beanType = formBeanConfig == null ? type : formBeanConfig.getType(); 
    }
    /**
     * Release any acquired resources.
     */
    public void release() {
        super.release();
        this.name = null;
    }

	@Override
	protected void renderAction(StringBuffer results) {
		HttpServletResponse response =
            (HttpServletResponse) this.pageContext.getResponse();
        results.append(" action=\"");
        results.append(this.action);
        results.append("\"");
	}
    
    
    



}
